import pandas as pd

LOGG = {}


class ParaWorker:
    # 居民数量参数
    def __init__(self):
        self.number_of_government_workers = 1360.0
        self.number_of_total_employment_workers = 7360.0
        self.number_of_households = 8000.0
        self.number_of_consumption_firm_workers = 5000.0
        self.number_of_capital_firm_workers = 1000.0


class ParaConsumptionFirm:
    # 消费品公司参数
    def __init__(self):
        self.unit_variable_cost_of_consumption_firm = 0.78125
        self.unit_cost_of_consumption_firm = 0.936688
        self.stock_of_capital_in_consumption_firm = 53863.59735
        self.deposits_consumption_firm_holds = 25000.0
        self.deposits_interests_of_consumption_firm = 62.034739
        self.amortization_of_consumption_firms = 4974.030293
        self.consumption_firm_inventory = 3200.0
        self.profits_of_consumption_firm = 2697.092071
        self.loans_of_consumption_firms = 52151.632187
        self.tax_of_consumption_firms = 485.476573
        self.dividends_of_consumption_firms = 1990.453948
        self.capital_of_consumption_firm = 40000.0
        self.loan_interests_of_consumption_firm = 388.22555


class ParaCapitalFirm:
    # 资本品公司参数
    def __init__(self):
        self.unit_cost_of_capital_firm = 2.5
        self.deposits_capital_firms_holds = 5000.0
        self.capital_firm_inventory = 200.0
        self.profits_of_capital_firm_before_tax = 381.466344
        self.loans_of_capital_firms = 1298.02106
        self.deposits_interests_of_capital_firm = 12.406948
        self.loan_interests_of_capital_firm = 9.662688
        self.change_inventory_of_capital_firm = 3.722084
        self.tax_of_capital_firms = 68.663942
        self.profits_of_capital_firm_after_tax = 312.802402
        self.dividends_of_capital_firms = 281.522162
        self.delta_loans_of_capital_firms = 9.662688


class ParaHouseholds:
    # 居民参数
    def __init__(self):
        self.net_income_of_households = 33556.108225
        self.tax_of_households = 7084.999367
        self.wages_of_households = 36800.0
        self.doles_of_households = 1280.0
        self.deposits_of_households = 80441.4173
        self.deposits_interests_of_households = 199.606495
        self.dividends_of_households = 2379.212356
        self.households_income_before_tax_and_dole = 39361.107592
        self.households_consumption_para_1 = 0.387838
        self.households_consumption_para_2 = 0.25
        self.real_households_consumption = 32000.0
        self.net_wealth_of_households = 80441.4173
        self.nominal_households_consumption = 32975.0
        self.households_wage = 5.0


class ParaBanks:
    # 银行参数
    def __init__(self):
        self.dividends_of_banks = 107.236245
        self.profits_of_bank_before_tax = 217.959848
        self.bank_receive_loans_interests = 397.888238
        self.bank_receive_bonds_interests = 94.119792
        self.bank_hold_bonds = 37930.276194
        self.bank_pay_deposits_interests = 274.048182
        self.tax_of_bank = 39.232773
        self.bank_reserves = 28665.089362
        self.net_wealth_of_bank = 9603.601504
        self.central_bank_hold_bonds = 28665.089362
        self.central_bank_profits = 71.129254
        self.ratio_of_bank_net_wealth_to_assets = 0.08

        self.capital_ratio_target = 0.18
        self.mandatory_liquidity_ratio = 0.08
        # CAPITAL_RATIO_TARGET = 0.18
        # MANDATORY_LIQUIDITY_RATIO = 0.08


class ParaGovernment:
    # 政府参数
    def __init__(self):
        self.bonds_government_issue = 66595.365556
        self.government_pay_bonds_interests = 165.249046
        self.government_collect_tax = 7678.372654


class ParaYield:
    # 产出参数
    def __init__(self):
        self.output_of_consumption = 32000.0
        self.nominal_output_of_consumption = 32975.0
        self.output_of_capital = 2000.0
        self.nominal_output_of_capital = 5375.0


class ParaInterestRate:
    # 利率参数
    def __init__(self):
        self.interest_rate_of_deposits = 0.0025
        self.interest_rate_of_loans = 0.0075
        self.interest_rate_of_bonds = 0.0025
        self.interest_rate_of_advances = 0.005


class ParaRatio:
    # 比率参数
    def __init__(self):
        self.ratio_of_dole_to_wage = 0.4
        self.labor_capital_ratio = 6.4
        self.ratio_of_deposits_to_wage = 1.0
        self.ratio_of_dividends_to_profits_left = 0.9
        self.ratio_of_dividends_to_profits_left_in_bank = 0.6
        self.ratio_of_inventory_to_output = 0.1

        self.tax_rate = 0.18
        self.capacity_of_utilization_of_capital = 0.8
        self.bank_min_reserve_rate = 0.08
        self.unemployment_rate_target = 0.05
        # UNEMPLOYMENT_RATE_BENCHMARK = 0.05
        # BANK_MIN_RESERVE_RATE = 0.08  # 最低银行存款准备金比率


class ParaSteadyState:
    # 稳态相关数据
    def __init__(self):
        self.steady_state_rate = 0.0075
        self.oo1_steady_state_rate = 0.992556
        self.oo2_steady_state_rate = 0.007444


class ParaPrice:
    # 价格相关
    def __init__(self):
        self.price_of_consumption = 1.030469
        self.price_of_capital = 2.6875


class ParaMarkup:
    # 加成比例
    def __init__(self):
        self.mark_up_of_consumption = 0.319
        self.mark_up_of_capital = 0.075


class ParaPara:
    # 其他参数
    def __init__(self):
        self.productivity_of_k_firm = 2.0
        self.productivity_of_c_firm = 1.0
        self.duration_or_capital = 20.0
        self.duration_or_loan = 20.0 # 贷款期限
        self.supp_para_for_consumption_unit_cost = 18.50802
        self.supp_para_for_stock_of_capital = 200.422688


class ParaAgent:
    # 多主体模拟参数(这里的参数不是求解的）
    def __init__(self):
        self.average_stockholder_per_firm = 5  # ?未被验证
        self.adaptive_lambda = 0.25

        self.degree_of_imperfect_information = 0.8
        self.c_firm_investment_elasticity = 0.2
        self.probability_of_switch = 0.8
        self.normal_d_mean = 0
        self.normal_d_dev = 0.0094

        # NORMAL_D_STD_DEV = 0.0094
        # NORMAL_D_MEAN = 0.0
        # INVESTMENT_ELASTICITY = 0.2  # 投资弹性
        # DEGREE_OF_IMPERFECT_INFORMATION = 0.8
        # PROBABILITY_OF_SWITCH = 0.8


class ParaNumber:
    # 各类主体数量
    def __init__(self):
        self.number_of_banks = 10
        self.number_of_c_firms = 100
        self.number_of_k_firms = 20


class ParaControl:
    def __init__(self):
        self.print = True
        self.apt = False


class ParaPro:
    # 汇集所有参数
    def __init__(self):
        self.w = ParaWorker()
        self.c = ParaConsumptionFirm()
        self.k = ParaCapitalFirm()
        self.h = ParaHouseholds()
        self.b = ParaBanks()
        self.g = ParaGovernment()
        self.y = ParaYield()
        self.ir = ParaInterestRate()
        self.ratio = ParaRatio()
        self.ss = ParaSteadyState()
        self.para = ParaPara()
        self.a = ParaAgent()
        self.n = ParaNumber()
        self.m = ParaMarkup()
        self.p = ParaPrice()
        self.ctrl = ParaControl()

        self.para.factor_of_batch_loan = self.batch_loan_factor()

    def batch_loan_factor(self):
        duration = self.para.duration_or_loan
        ss = self.ss.steady_state_rate
        v1 = [(duration - i) / (duration * (1 + ss)**i ) for i in range(int(duration))]
        return 1 / sum(v1)


class Para:
    def __init__(self, **kwargs):
        if len(kwargs) < 19:
            for key, value in kwargs.items():
                setattr(self, key, value)
        else:
            worker_kgs = {k: v for k, v in kwargs.items() if 'number_of' in k}
            self.w = Para(**worker_kgs)
            print("居民数量参数", len(worker_kgs))
            kwargs = {k: v for k, v in kwargs.items() if k not in worker_kgs}

            c_firm_kgs = {k: v for k, v in kwargs.items() if 'consumption_firm' in k}
            kwargs = {k: v for k, v in kwargs.items() if k not in c_firm_kgs}
            print("消费品公司参数", len(c_firm_kgs))
            self.c = Para(**c_firm_kgs)

            k_firm_kgs = {k: v for k, v in kwargs.items() if 'capital_firm' in k}
            kwargs = {k: v for k, v in kwargs.items() if k not in k_firm_kgs}
            print("资本品公司参数", len(k_firm_kgs))
            self.k = Para(**k_firm_kgs)

            h_kgs = {k: v for k, v in kwargs.items() if 'household' in k}
            kwargs = {k: v for k, v in kwargs.items() if k not in h_kgs}
            print("居民参数", len(h_kgs))
            self.h = Para(**h_kgs)

            b_kgs = {k: v for k, v in kwargs.items() if 'bank' in k}
            kwargs = {k: v for k, v in kwargs.items() if k not in b_kgs}
            print("银行参数", len(h_kgs))
            self.b = Para(**b_kgs)

            g_kgs = {k: v for k, v in kwargs.items() if 'government' in k}
            kwargs = {k: v for k, v in kwargs.items() if k not in g_kgs}
            print("政府参数", len(g_kgs))
            self.g = Para(**g_kgs)

            output_kgs = {k: v for k, v in kwargs.items() if 'output' in k}
            print("产出参数", len(output_kgs))
            self.y = Para(**output_kgs)
            kwargs = {k: v for k, v in kwargs.items() if k not in output_kgs}

            ir_kgs = {k: v for k, v in kwargs.items() if 'interest_rate' in k}
            print("利率参数", len(ir_kgs))
            self.ir = Para(**ir_kgs)
            kwargs = {k: v for k, v in kwargs.items() if k not in ir_kgs}

            ratio_kgs = {k: v for k, v in kwargs.items() if ('ratio' in k and 'ration' not in k)}
            print("比率参数", len(ratio_kgs))
            self.ratio = Para(**ratio_kgs)
            kwargs = {k: v for k, v in kwargs.items() if k not in ratio_kgs}

            ss_kgs = {k: v for k, v in kwargs.items() if 'steady_state' in k}
            print("ss参数", len(ratio_kgs))
            self.ss = Para(**ss_kgs)
            kwargs = {k: v for k, v in kwargs.items() if k not in ss_kgs}
            print("其余参数", len(kwargs))

            self.p = Para(**kwargs)


def load_ini_state_variables():
    path = "../input/ss_sfc_para.xlsx"
    data = pd.read_excel(path, index_col=0)
    para = dict(zip(data['para'].to_list(), data['解'].to_list()))
    return para


if __name__ == "__main__":
    paras = load_ini_state_variables()
    p = Para(**paras)
    pp = ParaPro()
